package handler

import (
	"errors"
	"fmt"
	"gitee.com/simple-set/simple.io/src/event"
	"gitee.com/simple-set/simple.io/src/process/codec"
	"gitee.com/simple-set/simple.proxy/src/config"
	"log/slog"
)

type TcpProxy struct {
	client *Client
}

func NewTcpProxy() *TcpProxy {
	client := NewClient()
	client.register(NewTcpBackend())
	return &TcpProxy{client: client}
}

func (t *TcpProxy) Active(session *event.Session, _ any) (any, error) {
	starterClient, err := t.client.DialTcp(config.Config.Tcp.Target)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = starterClient.Close()
	}()
	return starterClient.Request(session)
}

type TcpBackend struct{}

func NewTcpBackend() *TcpBackend {
	return &TcpBackend{}
}

func (t *TcpBackend) Active(backendSession *event.Session, value any) (any, error) {
	proxySession, ok := value.(*event.Session)
	if !ok {
		return nil, errors.New("invalid session: " + fmt.Sprintln(proxySession))
	}

	slog.Info(fmt.Sprintf("tcp %s -> %s", proxySession.Socket.RemoteAddr().String(), backendSession.Socket.RemoteAddr().String()))
	go func() {
		_, _ = codec.NewReadByteBuf(backendSession.Socket.Reader).WriteTo(proxySession.Socket)
	}()
	return codec.NewReadByteBuf(proxySession.Socket.Reader).WriteTo(backendSession.Socket)
}
